package com.tsd.core.utils;

import com.tsd.core.vo.HlpException;
import net.coobird.thumbnailator.Thumbnails;
import net.sf.image4j.use.Image4j;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * 图片工具类
 *
 * @Author: Lyc
 * @Date: Created in 2018/9/11 14:08
 * @Modefied By:
 */
public class ImageUtil {

    /**
     * 将原文件图片按照指定宽度、高度、质量、是否保持比例输出到指定文件
     *
     * @param sourceFilePath
     * @param destFilePath
     * @param width
     * @param height
     * @param outputQuality
     * @param keepAspectRatio
     * @throws IOException
     */
    public static void saveThumbnail(String sourceFilePath, String destFilePath, int width, int height, float outputQuality, boolean keepAspectRatio) throws IOException {
        Thumbnails.of(sourceFilePath).size(width, height).outputQuality(outputQuality).keepAspectRatio(keepAspectRatio).toFile(destFilePath);
    }

    /**
     * 将原文件图片按照指定缩放比率、质量输出到指定文件
     *
     * @param sourceFilePath
     * @param destFilePath
     * @param scale
     * @param outputQuality
     * @throws IOException
     */
    public static void saveThumbnail(String sourceFilePath, String destFilePath, float scale, float outputQuality) throws IOException {
        Thumbnails.of(sourceFilePath).scale(scale).outputQuality(outputQuality).toFile(destFilePath);
    }

    /**
     * 按指定高度 等比例缩放图片
     *
     * @param imageFile
     * @param newPath
     * @param newWidth  新图的宽度
     * @throws IOException
     */
    public static void zoomImageScale(File imageFile, String newPath, int newWidth) throws IOException {
        if (!imageFile.canRead()) {
            return;
        }
        BufferedImage bufferedImage = ImageIO.read(imageFile);
        if (null == bufferedImage) {
            return;
        }
        int originalWidth = bufferedImage.getWidth();
        int originalHeight = bufferedImage.getHeight();
        double scale = (double) originalWidth / (double) newWidth;    // 缩放的比例
        int newHeight = (int) (originalHeight / scale);
        zoomImageUtils(imageFile, newPath, bufferedImage, newWidth, newHeight);
    }

    /**
     * 按尺寸缩放图片
     *
     * @param imageFile
     * @param newPath
     * @throws IOException
     */
    public static void zoomImage(File imageFile, String newPath, int width, int height) throws IOException {
        if (imageFile != null && !imageFile.canRead()) {
            return;
        }
        BufferedImage bufferedImage = ImageIO.read(imageFile);
        if (null == bufferedImage) {
            return;
        }
        zoomImageUtils(imageFile, newPath, bufferedImage, width, height);
    }

    private static void zoomImageUtils(File imageFile, String newPath, BufferedImage bufferedImage, int width, int height)
            throws IOException {
        String suffix = StringUtils.substringAfterLast(imageFile.getName(), ".");
        // 处理 png 背景变黑的问题
        if (!HlpUtils.isEmpty(suffix) && !"jpg".equalsIgnoreCase(suffix)) {
            suffix = suffix.trim().toLowerCase();
            boolean flag1 = suffix.endsWith("png");
            boolean flag2 = suffix.endsWith("gif");
            if (flag1 || flag2) {
                BufferedImage to = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics2D g2d = to.createGraphics();
                to = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
                g2d.dispose();

                g2d = to.createGraphics();
                Image from = bufferedImage.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING);
                g2d.drawImage(from, 0, 0, null);
                g2d.dispose();
                ImageIO.write(to, suffix, new File(newPath));
            }
        } else {
            // 高质量压缩，其实对清晰度而言没有太多的帮助
//            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//            tag.getGraphics().drawImage(bufferedImage, 0, 0, width, height, null);
//
//            FileOutputStream out = new FileOutputStream(newPath);    // 将图片写入 newPath
//            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
//            JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(tag);
//            jep.setQuality(1f, true);    //压缩质量, 1 是最高值
//            encoder.encode(tag, jep);
//            out.close();

            BufferedImage newImage = new BufferedImage(width, height, bufferedImage.getType());
            Graphics g = newImage.getGraphics();
            g.drawImage(bufferedImage, 0, 0, width, height, null);
            g.dispose();
            ImageIO.write(newImage, suffix, new File(newPath));
        }
    }

    /**
     * 等比例改变图片尺寸
     *
     * @param nw       新图片的宽度
     * @param oldImage 原图片
     * @throws IOException
     */
    public static void constrainProportios(int nw, String oldImage) throws IOException {
        AffineTransform transform = new AffineTransform();
        BufferedImage bis = ImageIO.read(new File(oldImage));
        int w = bis.getWidth();
        int h = bis.getHeight();
        int nh = (nw * h) / w;
        double sx = (double) nw / w;
        double sy = (double) nh / h;
        transform.setToScale(sx, sy);
        AffineTransformOp ato = new AffineTransformOp(transform, null);
        BufferedImage bid = new BufferedImage(nw, nh, BufferedImage.TYPE_3BYTE_BGR);
        ato.filter(bis, bid);

        String newPath = StringUtils.substringBeforeLast(oldImage, ".") + "_3." + StringUtils.substringAfterLast(oldImage, ".");
        ImageIO.write(bid, "jpeg", new File(newPath));
//        ImageIO.write(bid, "jpeg", response.getOutputStream());
    }

    /**
     * 将图片转换为icon文件
     *
     * @param srcPath
     * @param newPath
     * @throws IOException
     */
    public static void zoomImage2Icon(String srcPath, String newPath, int width, int height) throws Exception {
        File imageFile = new File(srcPath);
        if (imageFile != null && !imageFile.canRead()) {
            return;
        }
        BufferedImage bufferedImage = ImageIO.read(imageFile);
        if (null == bufferedImage) {
            return;
        }
        String newPath1 = FileUtil.getAutoFileRename(srcPath);
        zoomImageUtils(imageFile, newPath1, bufferedImage, width, height);
        boolean ret = Image4j.Convert(newPath1, newPath);
        FileUtil.delete(newPath1);
        if (!ret) {
            throw new HlpException("转换失败，ret为false");
        }
    }
}
